package sysmiddleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/vueadmin/app/admin/internal/svc"
	sys "github.com/vueadmin/app/admin/sys"
	"github.com/vueadmin/app/admin/sys/sysvalidate"
	"github.com/vueadmin/utils"
	"github.com/vueadmin/utils/conv"
	"github.com/vueadmin/utils/response"
)

type UpdateFieldMiddleware struct {
	svcCtx *svc.ServiceContext
}

func NewUpdateFieldMiddleware(svcCtx *svc.ServiceContext) *UpdateFieldMiddleware {
	return &UpdateFieldMiddleware{
		svcCtx: svcCtx,
	}
}

// 修改数据表字段中间件
func (p UpdateFieldMiddleware) Handle() gin.HandlerFunc {
	return func(c *gin.Context) {
		var data sys.Field
		var field sys.Field
		var menu sys.Menu
		if err := utils.BindAndValid(c, &data); err != nil {
			response.Fail(c, err.Error())
			c.Abort()
			return
		}
		if err := new(sysvalidate.FieldValidate).Validate(&data); err != nil {
			response.Fail(c, err.Error())
			c.Abort()
			return
		}
		p.svcCtx.Db.Model(&sys.Menu{}).Where("menu_id", data.MenuId).Find(&menu)

		if data.OtherConfig["shuxing"] != nil {
			shuxing := data.OtherConfig["shuxing"].([]interface{})
			shuxingList := make([]string, 0)
			if len(shuxing) > 0 {
				for _, val := range shuxing {
					shuxingList = append(shuxingList, val.(string))
				}
			}
			if conv.IsValueInList("tabs", shuxingList) {
				var tabsCount int64
				if err := p.svcCtx.Db.Model(&sys.Field{}).Where("menu_id", data.MenuId).Where("other_config like ?", "%\"tabs%").Count(&tabsCount).Error; err != nil {
					response.Err(c, err)
					return
				}
				if tabsCount > 0 {
					response.Fail(c, "当前菜单已经设置选项卡字段")
					return
				}
			}
		}
		if sys.System.GetDBTypeByConnect(menu.Connect) != "mysql" {
			return
		}
		prefix := sys.System.GetPrefix(menu.Connect)

		if data.CreateTableField > 0 || (menu.PageType == 2 && data.Type == 30) {
			p.svcCtx.Db.Where("id", data.Id).Find(&field)
			var (
				defaultValue string
				length       string
				auto         string
				primary_key  string
				sql          string
			)
			if data.DefaultValue != "" {
				defaultValue = fmt.Sprintf("DEFAULT '%s'", data.DefaultValue)
			} else {
				defaultValue = "DEFAULT NULL"
			}

			pk := sys.System.GetPkByTable(p.svcCtx, menu.Connect, prefix+menu.Tablename)
			if pk == field.Field {
				auto = "AUTO_INCREMENT"
				defaultValue = "NOT NULL"
				primary_key = "primary_key"
			} else {
				auto = ""
				primary_key = ""
			}

			if conv.IsValueInList(data.Datatype, []string{"datetime", "longtext"}) {
				length = " null"
			} else {
				length = fmt.Sprintf("(%s)", conv.String(data.Length))
			}

			fieldlist := GetTableFields(p.svcCtx, menu.Connect, prefix+menu.Tablename)

			if conv.IsValueInList(field.Field, fieldlist) {
				sql = fmt.Sprintf("ALTER TABLE %s CHANGE %s %s %s%s COMMENT '%s' %s %s", prefix+menu.Tablename, field.Field, data.Field, data.Datatype, length, data.Title, defaultValue, auto)
			} else {
				sql = fmt.Sprintf("ALTER TABLE %s ADD %s %s%s COMMENT '%s' %s %s %s", prefix+menu.Tablename, field.Field, data.Datatype, length, data.Title, defaultValue, auto, primary_key)
			}
			if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sql).Error; err != nil {
				panic(err)
			}

			//判断索引是否存在
			if data.Indexdata != "" {
				indexs := getIndex(p.svcCtx, menu.Connect, prefix+menu.Tablename)
				if !conv.IsValueInList(data.Field, indexs) {
					if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sql).Error; err != nil {
						panic(err)
					}
				}
			}
			//更新菜单主键
			if pk == field.Field {
				if err := sys.System.Conn(p.svcCtx, menu.Connect).Model(&sys.Menu{}).Where("menu_id", data.MenuId).Update("pk", data.Field).Error; err != nil {
					panic(err)
				}
			}
		}
		c.Set("data", data)
		c.Next()
	}
}

// 查询数据表的所有字段
func getIndex(svcCtx *svc.ServiceContext, connect string, tableName string) []string {
	var data []map[string]interface{}
	var list []string
	sys.System.Conn(svcCtx, connect).Raw("show index from " + tableName).Scan(&data)

	for _, val := range data {
		list = append(list, val["Column_name"].(string))
	}

	return list
}
